package com.jintian.smart.kernel.autoconfigure.beetl;

import com.jintian.smart.kernel.autoconfigure.ConfigConstants;
import com.jintian.smart.kernel.autoconfigure.nacos.NacosTools;
import org.beetl.sql.ext.spring.BeetlSqlClassPathScanner;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.TypeFilter;

import java.util.Properties;
import java.util.function.Supplier;

public class BeetlSqlBeanUtils {

    private static void initBeetlSqlPropertiesFromNacos(Properties nacosProperties, ConfigurableEnvironment environment, BeetlSqlProperties beetlSqlProperties) {
        PropertySource<?> databasePropertySource = NacosTools.buildPropertySource(ConfigConstants.NACOS_DEFAULT_DATAID_DATABASEPROVIDER, nacosProperties, environment);
        try {
            beetlSqlProperties.init(environment);
        } finally {
            if (databasePropertySource != null)
                environment.getPropertySources().remove(databasePropertySource.getName());
        }
    }

    public static BeetlSqlProperties getOrCreateBeetlSqlProperties(BeanDefinitionRegistry registry, ConfigurableEnvironment environment) {
        BeetlSqlProperties bean = null;
        if (registry.containsBeanDefinition("beetlSqlProperties")) {
            bean = (BeetlSqlProperties) ((AbstractBeanDefinition) registry.getBeanDefinition("beetlSqlProperties")).getInstanceSupplier().get();
        } else {
            boolean local = "true".equals(environment.getProperty("smart.config.local"));
            BeetlSqlProperties beetlSqlProperties = new BeetlSqlProperties();
            if (local) {
                beetlSqlProperties.init(environment);
            } else {
                // 1. nacos属性
                Properties nacosProperties = NacosTools.buildNacosProperties(environment);
                // 2.nacos或Environment中加载DatabaseProvider
                initBeetlSqlPropertiesFromNacos(nacosProperties, environment, beetlSqlProperties);
            }
            bean = beetlSqlProperties;
            BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(BeetlSqlProperties.class,
                    new Supplier<BeetlSqlProperties>() {
                        @Override
                        public BeetlSqlProperties get() {
                            return beetlSqlProperties;
                        }
                    });
            registry.registerBeanDefinition("beetlSqlProperties", bdb.getBeanDefinition());
        }
        return bean;
    }

    public static void scanMapper(BeanDefinitionRegistry registry, ResourceLoader resourceLoader, BeetlSqlMapperScan scan) {
        if (scan.getBasePackages() == null || scan.getBasePackages().length == 0) {
            return;
        }
        BeetlSqlClassPathScanner scanner = new BeetlSqlClassPathScanner(registry);
        scanner.setResourceLoader(resourceLoader);
        scanner.setSqlManagerFactoryBeanName(scan.getSqlManager());
        scanner.setSuffix(scan.getMapperSuffix());
        scanner.registerFilters();

        Class<TypeFilter>[] filters = scan.getInclude();
        if (filters != null) {
            for (Class<TypeFilter> clazz : filters) {
                try {
                    scanner.addIncludeFilter(clazz.newInstance());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        filters = scan.getExclude();
        for (Class<TypeFilter> clazz : filters) {
            try {
                scanner.addExcludeFilter(clazz.newInstance());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        scanner.scan(scan.getBasePackages());
    }
}
